﻿using System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using UnityEngine;

public class PlayerCharacter : MonoBehaviour
{

    private void Awake()
    {
        InitWidget();
        //重力大一点.
        Physics.gravity = new Vector3(0, -12.0f, 0);
    }

    private void Update()
    {
        //TODO:面朝摄像机.
        FaceToCamera();

        UpTrigger();
    }

    private Rigidbody _rigidbody;
    private Collider _collider;

    private Animator _animator;

    private ZTest _zTest;

    private void InitWidget()
    {
        _rigidbody = GetComponent<Rigidbody>();
        _collider = GetComponent<Collider>();
        _zTest = GetComponentInChildren<ZTest>();
        _animator = transform.Find("Renderer").GetComponent<Animator>();
        _spriteRenderer = transform.Find("Renderer").GetComponent<SpriteRenderer>();
        _lightGameObject = transform.Find("Light").gameObject;
        _jumpEffectPrefab = Resources.Load("SmokeExplosionWhite") as GameObject;
    }

    /// <summary>
    /// 改变使用重力状态.
    /// </summary>
    /// <param name="useGravity"></param>
    public void ChangeGravityState(bool useGravity)
    {
        _rigidbody.useGravity = useGravity;
        //trigger.
        SetCanMoveState(useGravity);
        _rigidbody.velocity = Vector3.zero;
    }

    /// <summary>
    /// 旋转视角前的位置.
    /// </summary>
    private Vector3 _srcPos;

    /// <summary>
    /// 设置旋转视角前的位置.
    /// </summary>
    public void SetSrc()
    {
        _srcPos = transform.position;
    }

    /// <summary>
    /// 改变角色的位置,跟随摄像机.
    /// </summary>
    public void ChangePos()
    {
        Vector3 view = new Vector3();
        switch (_faceState)
        {
            case 0:
            case 2:
                view = Camera.main.WorldToViewportPoint(new Vector3(_collideTransform.position.x, transform.position.y,
            _srcPos.z));
                break;
            case 1:
            case 3:
                view = Camera.main.WorldToViewportPoint(new Vector3(_srcPos.x, transform.position.y,
            _collideTransform.position.z));
                break;
            default:
                break;
        }

        //深度
        int z = 10;
        //有时候旋转的时候块在后面.
        if (Camera.main.WorldToViewportPoint(_collideTransform.position).z > 20)
        {
            z = 30;
            //显示阴影.
            //Debug.Log(Camera.main.WorldToScreenPoint(transform.position));
            //UIManager.Instance.ShowShade(Camera.main.WorldToScreenPoint(transform.position));
        }
        Vector3 dst
            = Camera.main.ViewportToWorldPoint(new Vector3(view.x, view.y, z));
        
        transform.position = dst;

        //在跳跃中则停止.
        _rigidbody.velocity = Vector3.zero;
    }

    /// <summary>
    /// 面朝向摄像机.
    /// </summary>
    private void FaceToCamera()
    {
        transform.rotation = Camera.main.transform.rotation;
    }

    [HideInInspector]
    /// <summary>
    /// 碰撞接触到的物体.
    /// </summary>
    public Transform _collideTransform;

    //碰撞到的最近一次的落点.
    private Vector3 _lastPos;

    private void OnCollisionEnter(Collision info)
    {
        //移动过程中可能会碰到别的.
        if (!_canMove || !_isAlive)
        {
            return;
        }
        _collideTransform = info.collider.transform.parent;
        //Debug.Log("设置新的落点");
    }

    /// <summary>
    /// 保存位置.
    /// </summary>
    public void SavePos(Vector3 src)
    {
        //存档.
        _lastPos = new Vector3(src.x, transform.position.y, src.z);
        Debug.Log("更新了一次位置");
    }

    private bool _canMove = true;

    /// <summary>
    /// 设置可移动状态.
    /// </summary>
    /// <param name="state"></param>
    public void SetCanMoveState(bool state)
    {
        _canMove = state;
    }

    [SerializeField]
    private float _jumpSpeed = 1.0f;

    private bool _isJumping = false;

    private GameObject _jumpEffectPrefab;

    public void Jump()
    {
        if (!_canMove || _isJumping || !_isAlive)
        {
            return;
        }

        _rigidbody.velocity = new Vector3(0, _jumpSpeed, 0);
        _isJumping = true;

        _animator.SetTrigger("jump");
        AudioManager.Instance.PlaySound(12);
        StartCoroutine(JumpEffect());
    }

    private IEnumerator JumpEffect()
    {
        var go = ObjectPool.Spawn(_jumpEffectPrefab, transform.position - new Vector3(0, 1.25f, 0));
        yield return new WaitForSeconds(1);
        ObjectPool.Recycle(go);
    }

    /// <summary>
    /// 更新跳跃状态.
    /// </summary>
    public void UpdateJumpState()
    {
        _isJumping = false;
        //Debug.Log("落到了地板上");
    }

    /// <summary>
    /// 朝向的面的枚举.
    /// </summary>
    private int _faceState = 0;

    /// <summary>
    /// 改变面朝向的方向的状态.
    /// </summary>
    /// <param name="dir"></param>
    public void ChangeFaceState(int dir)
    {
        _faceState += dir;
        if (_faceState > 3)
        {
            _faceState = 0;
        }
        if (_faceState < 0)
        {
            _faceState = 3;
        }
        Debug.Log("改变了面朝向的方向，现在是" + _faceState);
        //改变朝向方向，对应隐藏激活.
        HideBoardManager.Instance.ActivateAll(_faceState);
        //影子该消了.
        UIManager.Instance.ShadeImgActive(false);
    }

    public void SetTriggerState(bool state)
    {
        _collider.isTrigger = state;
    }

    [SerializeField]
    private float _moveSpeed = 5.0f;

    public void Move(float dir)
    {
        if (!_canMove || !_isAlive)
        {
            return;
        }
        if (Mathf.Abs(dir) > 0)
        {
            _animator.SetBool("isWalking", true);
            transform.localScale = dir > 0 ? new Vector3(1, 1, 1) : new Vector3(-1, 1, 1);
        }
        else
        {
            _animator.SetBool("isWalking", false);
        }
        UIManager.Instance.ShadeImgActive(false);
        Vector3 velocity;
        switch (_faceState)
        {
            case 0:
                velocity = new Vector3(_moveSpeed * dir, _rigidbody.velocity.y, 0);
                if (!_zTest.RayAll(Vector3.back))
                {
                    //没有碰到.
                    //Debug.Log("修正位置");
                    transform.position = new Vector3(transform.position.x, transform.position.y, -10);
                }
                else
                {
                    UIManager.Instance.ShowShade(ScreenPos());
                }
                break;
            case 1:
                velocity = new Vector3(0, _rigidbody.velocity.y, _moveSpeed * dir);
                if (!_zTest.RayAll(Vector3.right))
                {
                    //没有碰到.
                    //Debug.Log("修正位置");
                    transform.position = new Vector3(10, transform.position.y, transform.position.z);
                }
                else
                {
                    UIManager.Instance.ShowShade(ScreenPos());
                }
                break;
            case 2:
                velocity = new Vector3(-_moveSpeed * dir, _rigidbody.velocity.y, 0);
                if (!_zTest.RayAll(Vector3.forward))
                {
                    //没有碰到.
                    //Debug.Log("修正位置");
                    transform.position = new Vector3(transform.position.x, transform.position.y, 10);
                }
                else
                {
                    UIManager.Instance.ShowShade(ScreenPos());
                }
                break;
            case 3:
                velocity = new Vector3(0, _rigidbody.velocity.y, -_moveSpeed * dir);
                if (!_zTest.RayAll(Vector3.left))
                {
                    //没有碰到.
                    //Debug.Log("修正位置");
                    transform.position = new Vector3(-10, transform.position.y, transform.position.z);
                }
                else
                {
                    UIManager.Instance.ShowShade(ScreenPos());
                }
                break;
            default:
                velocity = _rigidbody.velocity;
                break;
        }
        _rigidbody.velocity = velocity;
    }

    private bool _isAlive = true;

    public bool IsAlive
    {
        get { return _isAlive; }
    }

    /// <summary>
    /// 死亡.
    /// </summary>
    public void Die()
    {
        if (!_isAlive)
        {
            return;
        }
        _isAlive = false;
        //更新位置.
        _rigidbody.velocity = Vector3.zero;
        transform.position = new Vector3(0, 0, -10);
        Camera.main.transform.rotation = Quaternion.identity;
        Camera.main.transform.position = new Vector3(0, 1, -20);
        //闪烁提示.
        StartCoroutine(FlashHint());
    }

    private SpriteRenderer _spriteRenderer;

    private readonly float _flashTime = 0.25f;

    private IEnumerator FlashHint()
    {
        for (int i = 0; i < 4; i++)
        {
            _spriteRenderer.DOFade(0.3f, _flashTime);
            yield return new WaitForSeconds(_flashTime);
            _spriteRenderer.DOFade(1, _flashTime);
            yield return new WaitForSeconds(_flashTime);
        }
        //闪烁完毕.
        _isAlive = true;
    }

    private void UpTrigger()
    {
        if (_rigidbody.velocity.y > 0.01f)
        {
            _collider.isTrigger = true;
        }
        else
        {
            _collider.isTrigger = false;
        }
    }

    /// <summary>
    /// 获取自身在屏幕坐标系的位置.
    /// </summary>
    /// <returns></returns>
    private Vector2 ScreenPos()
    {
        return Camera.main.WorldToScreenPoint(transform.position);
    }

    private GameObject _lightGameObject;

    public void ShowLight()
    {
        _lightGameObject.SetActive(true);
        _lightGameObject.GetComponent<SpriteRenderer>().DOFade(0, 0.5f).From();
    }

}
